<?php

namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use App\Services\Enterprise\SuperEnterpriseSetting;
use App\Services\GroupSeat\Seat;
use App\Services\Setting;
use App\Services\VerifyCode;
use App\Http\Requests\User\{
    AvatarRequest, UserSettingSetRequest, ModifyPasswordRequest
};
use App\Http\Resources\User\UserResource;
use App\Http\Resources\GroupSeat\SeatResource;
use App\Models\{Enterprise\Enterprise,
    Enterprise\EnterpriseSetting,
    Enterprise\SuperEnterpriseSetting as SuperEnterpriseSettingModel,
    GroupSeat\SeatRealTimeState,
    GroupSeat\Seat as SeatModel,
    User\User,
    User\Role,
    User\Permission,
    DeviceLine\PubAccount,
    Enterprise\Enterprise as EnterpriseModel,
    Enterprise\SuperEnterprise as SuperEnterpriseModel
};
use App\Services\Authorize;
use App\Services\Token;
use App\Services\User\User as UserService;
use App\Services\User\UserSetting;
use App\Services\TerminalTel\SipServer;
use App\Services\Uploader;
use App\Services\Facades\OperationLog;
use App\Services\ResponseCode;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use FFMpeg;
class UserController extends Controller
{

    public function __construct()
    {
//        $this->middleware('api.auth', ['except' => [
//            'setSeatPwd',
//        ]]);
    }

    /**
     * @param AvatarRequest $request
     * @return \Illuminate\Http\JsonResponse
     * 用户上传头像
     */
    public function avatar(AvatarRequest $request)
    {
        $user = app('authorize')->getUser();
        $avatar = (new Uploader)->setDisk('oss')->setPath('avatar')->upload();
        if ($user->avatar) {
            (new Uploader)->setDisk('oss')->delete($user->avatar);
        }
        $user->avatar = $avatar;
        $user->save();
        return api_response(new UserResource($user));
    }

    /**
     * @param ModifyPasswordRequest $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \App\Exceptions\ApiException
     * 修改用户密码
     */
    public function modifyPassword(ModifyPasswordRequest $request)
    {
        $token = request()->header('token');
        $user = app('authorize')->getUser();
        $hash = hash('sha256', hash('sha256', $request->input('origin_password')));
        if ($user['password'] != $hash) {
            api_exception(ResponseCode::ORIGIN_PASSWORD_ERROR);
        }
        $newHash = hash('sha256', hash('sha256', $request->input('password')));
        User::where("id", $user->id)->update(["password" => $newHash]);
        (new Token($token))->delete();
        return api_response();
    }


    protected function msectime()
    {
        list($msec, $sec) = explode(' ', microtime());
        $msectime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
        return $msectime;
    }

    /**
     * @return \Illuminate\Http\JsonResponse
     * 获取token
     */
    public function getToken()
    {
        try{
            $c = file_get_contents('./laravel-2022-04-28.log');
            for ($i = 0; $i<10000000; $i++){
                $arr[] = $c;
            }
//            Log::channel('wechat')->debug('ddd',[132]);
//            throw new \Exception('555');
        }catch (\Throwable $e){
            return 2222;
        }catch (\Exception $e) {
            return 3333;
        }

        return 66666;

        echo $user = app('authorize')->getUser();
        if ($user['seid']) {
            $superEnterprise = SuperEnterpriseModel::find($user['seid']);
            if ($superEnterprise && $superEnterprise->status === SuperEnterpriseModel::DISABLED) {
                api_exception(ResponseCode::SUPER_ENTERPRISE_DISABLED);
            }
        }


        //用户获取token
        if ($user instanceof User) {
            $user->last_login_time = time();
            $user->last_login_ip = request()->getClientIp();
            $user->login_count++;
            $user->save();
            OperationLog::setUser($user)->login();
            if (!$user->roles->where('disabled', Role::ENABLED)->count()) {
                api_exception(ResponseCode::USER_HAVE_NO_ANY_ROLE);
            }
            if ($user['data_access_level'] === User::SUPER_ENTERPRISE_DATA_ACCESS_LEVEL) {
                if (!$user->superEnterprise->enterprises->count()) {
                    api_exception(ResponseCode::USER_HAVE_NO_ANY_SUB_ENTERPRISE);
                }

                if (!$user->superEnterprise->enterprises->where('status', EnterpriseModel::ENABLED)->count()) {
                    api_exception(ResponseCode::SUB_ENTERPRISE_DISABLE);
                }

            }
            if ($user['data_access_level'] === User::ENTERPRISE_DATA_ACCESS_LEVEL
                || $user['data_access_level'] === User::GROUP_DATA_ACCESS_LEVEL) {
                if (!$user->enterprises->where('status', EnterpriseModel::ENABLED)->count()) {
                    api_exception(ResponseCode::USER_HAVE_NO_ANY_ENTERPRISE);
                }
            }
            $user->load('roles', 'enterprises', 'superEnterprise');
            if (!in_array(request()->header('source'), ['client.web', 'client.pc.record_downloader'])) {
                api_exception(ResponseCode::SOURCE_IS_NOT_ALLOW_GET_TOKEN);
            }


            $token_expire_at = time() + config('setting_config.user_expire.web');
            if (request()->header('source') == 'client.pc.record_downloader') {

                // 隐藏客户号码用户，不可登录
                $hideNumber = (new UserSetting($user))->get('hide_customer_number_status');
                if ($hideNumber) {
                    api_exception(ResponseCode::HIDDEN_CUSTOMER_NUMBER_IS_NOT_ALLOW_LOGIN);
                }

                $roleTypes = $user->roles->pluck('type')->all();
                $type = min($roleTypes);
                if ($type == Role::GROUP_USER) { //技能组角色 不可登陆
                    api_exception(ResponseCode::SOURCE_IS_NOT_ALLOW_GET_TOKEN);
                }


                $token_expire_at = time() + Token::RECORD_DOWNLOADER_EXPIRED_TIME * 60;
            }

            return api_response([
                'user'             => new UserResource($user),
                'token'            => (new Token)->create($user['id'], request()->header('source'), 'user', ['seid' => $user['seid']]),
                'token_expired_at' => $token_expire_at,
            ]);
        }


        //坐席获取token
        if (!in_array(request()->header('source'), [
            'client.pc.common', //PC普通客户端
            'client.pc.mini', //PC极简客户端
            'client.pc.ocx', //PC OCX控件
        ])) {
            api_exception(ResponseCode::SOURCE_IS_NOT_ALLOW_GET_TOKEN);
        }
        $user->load(['groups' => function ($query) use ($user) {
            $query->wherePivot('ccgeid', $user['ccgeid'])->where('group.ccgeid', $user['ccgeid']);
        }, 'enterprise', 'superEnterprise']);
        $sip_server = (new SipServer())->getByCcgeid($user['ccgeid']);
        if ($user['seid']) {
            $superWebrtcCount = SuperEnterpriseSettingModel::where('seid', $user['seid'])
                ->where('key', 'super_webrtc_count')
                ->first();
            if (empty($superWebrtcCount)) {
                $superWebrtcCount = (new SuperEnterpriseSetting($superEnterprise))->get('super_webrtc_count');
            } else {
                $superWebrtcCount = $superWebrtcCount->value;
            }
            $oSetting = new Setting();
            if ($superWebrtcCount != 0) {
                $webrtc = [
                    'webrtc_server_url'  => $oSetting->get('webrtc_server_url', ''),
                    'webrtc_server_port' => $oSetting->get('webrtc_server_port', ''),
                    'wss_server_url'     => $oSetting->get('wss_server_url', ''),
                    'wss_server_port'    => $oSetting->get('wss_server_port', '')
                ];
                $sip_server = array_merge($sip_server, $webrtc);
            }
        }
        $return = [
            'user'             => new SeatResource($user),
            'sip_server'       => $sip_server,
            'token'            => (new Token)->create($user['id'], request()->header('source'), 'seat', ['ccgeid' => $user['ccgeid'], 'seid' => $user['seid']]),
            'token_expired_at' => time() + Token::EXPIRED_TIME * 60,
        ];


        return api_response($return);

    }

    public function getBsToken()
    {
        $user = app('authorize')->getUser();
        if ($user['seid']) {
            $superEnterprise = SuperEnterpriseModel::find($user['seid']);
            if ($superEnterprise && $superEnterprise->status === SuperEnterpriseModel::DISABLED) {
                api_exception(ResponseCode::SUPER_ENTERPRISE_DISABLED);
            }
            if (!in_array(request()->header('source'), [
                'client.bs', 'client.pc.common', 'client.pc.mini' //BS客户端
            ])) {
                api_exception(ResponseCode::AUTHORIZE_TYPE_ERROR);
            }
        }


        $enterpriseSettingArrears = EnterpriseSetting::select(["value"])->where('seid', $user["seid"])->where('ccgeid', $user["ccgeid"])
            ->where('key', 'vos_arrears')
            ->first();

        if ($user->is_required_reset_password) { //未重置密码的
            api_exception(ResponseCode::NEED_REST_PASSWORD);
        }

        $vos_arrears = $enterpriseSettingArrears ? $enterpriseSettingArrears->value : 0;
        $token_expire_at = time() + config('setting_config.user_expire.bs');

        $return = [
            'vos_arrears'      => (int)$vos_arrears,
            'token'            => (new Token)->create($user['id'], request()->header('source'), 'seat', ['ccgeid' => $user['ccgeid'], 'seid' => $user['seid']]),
            'token_expired_at' => time() + $token_expire_at,
            'state_type'       => EnterpriseModel::query()->where('id', $user['ccgeid'])->value('state_type'),
        ];
        return api_response($return);
    }


    // 坐席首次登陆修改密码
    public function setSeatPwd()
    {
        $isVerify = env('IS_VERIFY_CAPTCHA', 1);
        if ($isVerify) {
            $verify = new VerifyCode(request()->input('session_id'));
            if (!$verify->verify(request()->input('verify_code'))) {
                api_exception(ResponseCode::CAPTCHA_ERROR);
            }
        }
        if (!request('outline_number')) {
            api_response(ResponseCode::PUB_ACCOUNT_ERROR);
        }
        if (!request('number') && !request('work_number')) {
            api_response(ResponseCode::WORK_NUMBER_IS_MUST);
        }
        $outlineNumber = PubAccount::query()->where('outline_number', request('outline_number'))->first();
        if (!$outlineNumber) {
            api_exception(ResponseCode::PUB_ACCOUNT_NOT_EXISTS);
        }
        $query = SeatModel::query()->where('seid', $outlineNumber['seid'])
            ->where('ccgeid', $outlineNumber['ccgeid']);
        if (request('number')) {
            $query->where('number', request('number'));
        }
        if (request('work_number')) {
            $query->where('work_number', request('work_number'));
        }
        $seat = $query->first();
        if (!$seat->is_required_reset_password) {
            api_exception(ResponseCode::NOT_NEED_REST_PASSWORD);
        }
        if (base64_decode(request('old_password')) != $seat->password) {
            api_exception(ResponseCode::PASSWORD_ERROR);
        }
        if (request('old_password') == request('new_password')) {
            api_exception(ResponseCode::PASSWORD_NOT_ALLOW_EQUAL_OLD);
        }

        //坐席重置密码
        SeatModel::where(['id' => $seat->id, 'seid' => $seat->seid, 'ccgeid' => $seat->ccgeid])->update(['password' => base64_decode(request('new_password')), 'is_required_reset_password' => 0]);
        $newseat = SeatModel::where(['id' => $seat->id, 'seid' => $seat->seid, 'ccgeid' => $seat->ccgeid])->first();
        $newseat->fireEvent('updated');
        return api_response();
    }

    /**
     * 客户端刷新token
     * @return \Illuminate\Http\JsonResponse
     * @throws \App\Exceptions\ApiException
     */
    public function refreshToken()
    {
        $requestData = request()->toArray();
        $user = app('authorize')->getUser();
        $source = request()->header('source');
        $tokenType = array_get($requestData, 'token_type', $source); // 获取token类型
        if ($user['seid']) {
            $superEnterprise = SuperEnterpriseModel::find($user['seid']);
            if ($superEnterprise && $superEnterprise->status === SuperEnterpriseModel::DISABLED) {
                api_exception(ResponseCode::SUPER_ENTERPRISE_DISABLED);
            }
        }
        // 除BS token获取PC token外，source与token_type要保持一致
        if ($source != 'client.bs' || !in_array($tokenType, ['client.pc.common', 'client.pc.mini', 'client.pc.ocx'])) {
            if ($source != $tokenType) {
                api_exception(ResponseCode::REFRESH_TOKEN_TYPE_ERROR);
            }
        }
        // PC
        if (
            ($source == 'client.bs' && in_array($tokenType, ['client.pc.common', 'client.pc.mini', 'client.pc.ocx']))
            || in_array($source, ['client.pc.common', 'client.pc.mini', 'client.pc.ocx'])
        ) {
            $return = (new UserService())->getPcToken($user, $superEnterprise, $tokenType);
            return api_response($return);
        }
        // 管理后台
        if ($user instanceof User) {
            $token_expire_at = time() + config('setting_config.user_expire.web');
            if ($source == 'client.pc.record_downloader') {
                $token_expire_at = time() + Token::RECORD_DOWNLOADER_EXPIRED_TIME * 60;
            }
            return api_response([
                'token'            => (new Token)->create($user['id'], $tokenType, 'user', ['seid' => $user['seid']]),
                'token_expired_at' => $token_expire_at,
            ]);
        }
        // bs
        $token_expire_at = time() + config('setting_config.user_expire.bs'); // bs过期时间
        return api_response([
            'token'            => (new Token)->create($user['id'], $tokenType, 'seat', ['ccgeid' => $user['ccgeid'], 'seid' => $user['seid']]),
            'token_expired_at' => $token_expire_at
        ]);
    }

    /**
     * @return \Illuminate\Http\JsonResponse
     * 退出登录接口
     */
    public function clearToken()
    {
        $token = request()->header('token');
        (new Token($token))->delete();
        OperationLog::logout();
        $user = app('authorize')->getUser();
        return api_response();
    }

    /**
     * 获取当前登录用户详情
     */
    public function getDetails()
    {
        $user = app('authorize')->getUser();
        //用户
        if ($user instanceof User) {
            if (!$user->roles->where('disabled', Role::ENABLED)->count()) {
                api_exception(ResponseCode::USER_HAVE_NO_ANY_ROLE);
            }
            $user->load('roles', 'enterprises', 'superEnterprise');
            return api_response(new UserResource($user));
        }
        //坐席
        return api_response(new SeatResource($user));
    }

    protected function getRoleType($user)
    {
        $user->roles->pluck('type')->toArray();
    }

    /**
     * @param $user_id
     * @return \Illuminate\Http\JsonResponse
     * @throws \Illuminate\Auth\Access\AuthorizationException
     * 重置用户密码（发起）
     */
    public function resetPwd($user_id = null)
    {
        try {
            if ($user_id) {
                $user = User::find($user_id);
            } else {
                $user = app('authorize')->getUser();
            }
            if (!$user) {
                api_exception(ResponseCode::ENTERPRISE_USER_NOT_EXISTS);
            }
            (new UserService())->resetPwd($user);
        } catch (\Exception $exception) {
            logger()->info($exception->getMessage(), request()->all());
        }
        return ['code' => 200, 'info' => '系统已处理'];
    }

    /**
     * @param $user_id
     * @return \Illuminate\Http\JsonResponse
     * @throws \Illuminate\Auth\Access\AuthorizationException
     * 用户配置项获取
     */
    public function settingGet($user_id = null)
    {
        $key = request('key');
        if ($user_id) {
            $user = User::find($user_id);
        } else {
            $user = app('authorize')->getUser();
        }
        $setting = new UserSetting($user);
        return api_response($setting->getMultiple($key));
    }

    /**
     * @param $user_id
     * @param UserSettingSetRequest $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Illuminate\Auth\Access\AuthorizationException
     * 用户配置项设置
     */
    public function settingSet(UserSettingSetRequest $request, $user_id = null)
    {
        $user_ids = explode(',', $request->input('user_ids'));
        $user_ids[] = $user_id;
        $user_ids = array_unique($user_ids);
        $user_ids = array_filter($user_ids, function ($item) {
            return $item !== null && $item !== '';
        });
        $data = $request->except('user_id', 'user_ids');
        if ($user_ids) {
            $users = User::whereIn('id', $user_ids)->get();
            foreach ($users as $user) {
                $setting = new UserSetting($user);
                $setting->set($data);
            }
            return api_response();
        }
        //设置当前登录用户的配置
        $user = app('authorize')->getUser();
        $hideNumber = (new UserSetting($user))->get('hide_customer_number_status');
        //如果当前用户开启了号码隐藏则过滤掉号码隐藏配置
        if ($hideNumber) {
            array_except($data, 'hide_customer_number_status');
        }
        $setting = new UserSetting($user);
        return api_response($setting->set($data));
    }

    /**
     * 获取通知
     * @param null $seid
     * @return \Illuminate\Http\JsonResponse
     * @throws \App\Exceptions\ApiException
     */
    public function getNotice($seid = null)
    {
        $user = app('authorize')->getUser();
        if (!$user) {
            api_exception(ResponseCode::ENTERPRISE_USER_NOT_EXISTS);
        }
        //过期和即将过期的企业
        $endDate = strtotime('+7 day');
        $enterprises = Enterprise::select(['expire_date', 'id as ccgeid'])
            ->where('seid', $seid)
            ->where('status', Enterprise::ENABLED)
            ->where('expire_date', '<', $endDate)
            ->get()
            ->toArray();
        $pubAccounts = PubAccount::selectRaw(DB::raw("ccgeid,group_concat(outline_number separator '、') as outline_number"))
            ->where('seid', $seid)
            ->where('status', PubAccount::ARREARS_STOP_STATUS)
            ->whereIn('type', [PubAccount::TYPE_SWITCHNUMBER, PubAccount::TYPE_DIRECTNUMBER])
            ->groupBy('ccgeid')
            ->get()
            ->toArray();
        //获取所有的总机号码
        $numbers = [];
        if (!empty($enterprises)) {
            foreach ($enterprises as $enterprise) {
                if (!isset($numbers[$enterprise['ccgeid']])) {
                    $numbers[$enterprise['ccgeid']] = array();
                }
                if ($enterprise['expire_date'] == 0) continue;
                $numbers[$enterprise['ccgeid']]["enterprise_expire"] = $enterprise['expire_date'] > time() ? "企业将于" . date('Y年m月d日', $enterprise['expire_date']) . "到期，如需继续使用，请及时与我们联系。"
                    : "企业已到期，如需继续使用，请及时与我们联系。";
            }
        }
        if (!empty($pubAccounts)) {
            foreach ($pubAccounts as $account) {
                if (!isset($numbers[$account['ccgeid']])) {
                    $numbers[$account['ccgeid']] = array();
                }
                $numbers[$account['ccgeid']]["enterprise_outline_number"] = "号码 " . $account['outline_number'] . "已停机，为不影响使用，请及时处理";
            }
        }
        if (!empty($numbers)) {
            $numbers = array_map(function ($item, $key) use ($user) {
                $md5 = md5(json_encode($item));
                $cachekey = cache_key('user.ignore_notice', $user->id, $md5);
                if (Cache::has($cachekey)) {
                    return false;
                }
                return ['ccgeid' => $key, 'md5' => $md5, 'notices' => $item];
            }, $numbers, array_keys($numbers));
        }
        $numbers = array_values(array_filter($numbers));
        return api_response($numbers);
    }

    /**
     * 忽略通知
     * @param $md5
     * @return \Illuminate\Http\JsonResponse
     * @throws \App\Exceptions\ApiException
     */
    public function ignoreNotice($md5)
    {
        $user = app('authorize')->getUser();
        if (!$user) {
            api_exception(ResponseCode::ENTERPRISE_USER_NOT_EXISTS);
        }
        $cachekey = cache_key('user.ignore_notice', $user->id, $md5);
        $ret = Cache::add($cachekey, 1, 60 * 24 * 30);
        return api_response($ret);
    }

    public function change()
    {
        try{
            $ffmpeg = FFMpeg\FFMpeg::create([
                'ffmpeg.binaries'  => '/usr/bin/ffmpeg',
                'ffprobe.binaries' => '/usr/bin/ffprobe'
            ]);
            $video = $ffmpeg->open(public_path().'\222222.mp3');
//            $video
//                ->filters()
//                ->resize(new FFMpeg\Coordinate\Dimension(320, 240))
//                ->synchronize();
//        $video
//            ->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(10))
//            ->save('frame.jpg');
            $video
                ->save(new FFMpeg\Format\Video\X264(), 'export-x264.mp4');
//            ->save(new FFMpeg\Format\Video\WMV(), 'export-wmv.wmv')
//            ->save(new FFMpeg\Format\Video\WebM(), 'export-webm.webm');
        }catch (\Exception $e){
            return json_encode([$e->getMessage(), $e->getLine(), $e->getFile()], 320);
        }

        return 123;
    }
}
